"""
编写人：caoyong，时间：2022-11-23

"""
import datetime
import decimal


class SqlData:
    def __init__(self, db, str_replace_dict={}):
        if not hasattr(self, 'db_type'):
            self.db_type = ''
        self.cursor = db.cursor()  # 使用 cursor() 方法创建一个游标对象 cursor
        self.str_replace_dict = str_replace_dict  # 要替换的字符串，不同的数据库要替换的字符串不一样

    def get_value(self, _):
        """
        :param _: 数据库返回的类型
        :return: json可接受的类型
        """
        if type(_) in [datetime.datetime, datetime.date, datetime.timedelta]:
            _ = str(_)
        elif type(_) in [decimal.Decimal]:
            _ = round(float(_), 14)
        elif self.db_type == 'pymssql' and type(_) == str:
            _ = _.encode('latin1').decode('gb2312')
        return _

    def set_value(self, value):
        """
        格式化为数据库可接受的类型（字符串）
        :param value:
        :return:
        """
        if value is None:
            ret_value = 'NULL'
        elif type(value) in [int, float, bool]:
            ret_value = str(value)
        else:
            value = str(value)  # 转为字符串
            for k, v in self.str_replace_dict.items():  # 遍历要替换的字符串
                value = value.replace(k, v)  # 替换字符串
            ret_value = "'{}'".format(value)
        return ret_value

    def query(self, sql):  # 数据库查询操作 ，返回列表
        self.cursor.execute(sql)  # 执行SQL
        fields = [_[0] for _ in self.cursor.description]
        data_list = []
        for __ in self.cursor.fetchall():
            data = dict()
            for i, _ in enumerate(__):
                data[fields[i]] = self.get_value(_)
            data_list.append(data)
        return data_list

    def get_row(self, sql):  # 数据库查询操作，返回字典 ，注意：只取第一条数据
        self.cursor.execute(sql)  # 执行SQL
        data = self.cursor.fetchone()  # 使用 fetchone() 方法获取一条数据
        fields = [_[0] for _ in self.cursor.description]

        if data:
            values = []
            for i, _ in enumerate(data):  # 循环字段名称
                values.append(self.get_value(_))
        else:
            values = [None] * fields.__len__()
        row_info = dict(zip(fields, values))
        return row_info

    def get_one(self, sql):  # 数据库查询操作，返回一个字段，注意：只取第一条数据的第一个字段
        self.cursor.execute(sql)  # 执行SQL
        data = self.cursor.fetchone()  # 使用 fetchone() 方法获取一条数据
        if data is None:  # None 为未查询到数据
            _ = None
        else:
            _ = data[0]  # 取第一个字段
        return self.get_value(_)

    def execute(self, sql):  # 自定义 sql 执行语句 ，返回影响行数
        self.cursor.execute(sql)  # 执行SQL
        return self.cursor.rowcount  # 返回影响行数

    def add(self, table_name, add_data, way='INSERT', get_sql=False):
        if type(add_data) == dict:  # 单条数据写入
            insert_data = [add_data]
        elif type(add_data) == list:  # 多条数据写入
            insert_data = add_data
        if insert_data.__len__() == 0:
            return 0
        fields = list(insert_data[0].keys())  # 字段
        values = []
        for insertInfo in insert_data:  # 循环待写入数据
            for key in insertInfo:
                insertInfo[key] = self.set_value(insertInfo[key])
            values.append("({})".format(','.join(list(insertInfo.values()))))
        insert_sql = '{} INTO {} ({}) VALUES {}'.format(way, table_name, ','.join(fields), ','.join(values))
        if get_sql:
            return insert_sql
        else:
            ret = self.execute(insert_sql)  # 执行语句并获取影响行数
            return ret  # 返回影响行数

    def update(self, table_name, data, where, get_sql=False):
        """
        更新数据库数据
        :param table_name: 表名
        :param data: 更新的数据，字典，键：字段名，值：更新的数据库值
        :param where:
        :param get_sql:
        :return:
        """
        update_set_list = []
        for field, value in data.items():
            value_str = self.set_value(value)
            update_set_list.append('{} = {}'.format(field, value_str))
        update_set_str = ' , '.join(update_set_list)
        update_sql = 'update {} set {} where {}'.format(table_name, update_set_str, where)
        if get_sql:
            return update_sql
        else:
            # print(update_sql)
            ret = self.execute(update_sql)  # 执行语句并获取影响行数
            return ret  # 返回影响行数

    def __del__(self):
        # print('execute db close')
        self.close()

